package com.rw.map.config;

import java.util.List;
import java.util.Set;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;

import org.springframework.messaging.handler.annotation.support.MethodArgumentNotValidException;
import org.springframework.stereotype.Component;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.rw.map.model.Result;
import com.rw.map.utils.StringUtils;

@ControllerAdvice
@Component
public class GlobalExceptionHandler {

	private static Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);

	/**
	 * 
	 *
	 * @param e
	 * @return
	 */
	@ExceptionHandler(RuntimeException.class)
	@ResponseBody
	public Result handler(RuntimeException e) {
		logger.error("系统异常", e);
		return Result.failed("系统繁忙，请稍后再试");
	}
	
	@ExceptionHandler(value = BindException.class)
	@ResponseBody
	public Result exceptionHandle(BindException exception) {

		BindingResult result = exception.getBindingResult();
		StringBuilder errorMsg = new StringBuilder();

		List<FieldError> fieldErrors = result.getFieldErrors();
		fieldErrors.forEach(error -> {
			logger.error("field: {}, msg: {}", error.getField(), error.getDefaultMessage());
			errorMsg.append(error.getDefaultMessage()).append(",");
		});
		return Result.failed(errorMsg.substring(0, errorMsg.length() - 1));
	}

	/**
	 * Hibernate Validator参数校验异常处理
	 *
	 * @param e
	 * @return
	 */
	@ExceptionHandler(MethodArgumentNotValidException.class)
	@ResponseBody
	public Result handler(MethodArgumentNotValidException e) {
		StringBuilder sb = new StringBuilder();
		BindingResult bindingResult = e.getBindingResult();
		if (bindingResult.hasErrors()) {
			List<ObjectError> errors = bindingResult.getAllErrors();
			errors.forEach(p -> {
				FieldError fieldError = (FieldError) p;
				sb.append("[" + fieldError.getField() + "]" + fieldError.getDefaultMessage() + ",");
				logger.error("Data check failure : object{" + fieldError.getObjectName() + "},field{"
						+ fieldError.getField() + "},errorMessage{" + fieldError.getDefaultMessage() + "}");
			});
		}
		return Result.failed(sb.substring(0, sb.length() - 1));
	}

	/**
	 * MissingServletRequestParameterException异常处理
	 *
	 * @param e
	 * @return
	 */
	@ExceptionHandler(MissingServletRequestParameterException.class)
	@ResponseBody
	public Result handler(MissingServletRequestParameterException e) {
		return Result.failed(e.getMessage());
	}

	/**
	 * Spring Validator参数校验异常处理
	 *
	 * @param e
	 * @return
	 */
	@ExceptionHandler(ConstraintViolationException.class)
	@ResponseBody
	public Result handler(ConstraintViolationException e) {
		StringBuilder sb = new StringBuilder();
		Set<ConstraintViolation<?>> constraintViolations = e.getConstraintViolations();
		for (ConstraintViolation<?> constraintViolation : constraintViolations) {
			String message = constraintViolation.getMessage();
			if (!StringUtils.isEmpty(message)) {
				// 直接返回第一个错误信息
				sb.append(message);
			}
		}

		return Result.failed(sb.toString());
	}
}
